package cn.kent.high.threadLocalRandom;

import java.util.concurrent.ThreadLocalRandom;

/**
 * 为了弥补{@link java.util.Random}在多线程高并发下的缺陷
 * 设计上类似ThreadLocal，将老种子维护在本地线程内存副本中，每次生成随机数都是从自己线程的本地内存副本中取老种子生成新种子，从而不用去竞争原子性指令资源。
 *      提高了并发性能。
 *
 * ThreadLocalRandom就是个工具类，只包含与线程无关的通用算法，所以是线程安全的。
 *
 * 两个原子性变量，当初始化时调用线程的种子和探针变量时会用到他们
 * // Generates per-thread initialization/probe field
 * private static final AtomicInteger probeGenerator= new AtomicInteger();
 * // The next seed for default constructors.
 * private static final AtomicLong seeder=new AtomicLong(initialSeed());
 */
public class ThreadLocalRandomTest {
    public static void main(String[] args) {
        // 单例获取当前线程的随机数生成器 current方法由static修饰，多个线程返回的是同一个ThreadLocalRandom实例
        ThreadLocalRandom random = ThreadLocalRandom.current();
        for (int i = 0; i < 10; i++) {
            System.out.println(random.nextInt(10));
        }
         long GAMMA = 0x9e3779b97f4a7c15L;
        System.out.println(GAMMA);
    }

    //     Unsafe 机制
    // //  Unsafe mechanics
    //     private static final sun.misc.Unsafe UNSAFE;
    //     private static final long SEED;
    //     private static final long PROBE;
    //     private static final long SECONDARY;
    //     static {
    //         try {
    //             UNSAFE = sun.misc.Unsafe.getUnsafe(); // 获取Unsafe实例
    //             Class<?> tk = Thread.class;
    //             SEED = UNSAFE.objectFieldOffset
    //                 (tk.getDeclaredField("threadLocalRandomSeed")); // 获取Thread类里面的threadLocalRandomSeed变量在Thread实例里面的偏移量
    //             PROBE = UNSAFE.objectFieldOffset
    //                 (tk.getDeclaredField("threadLocalRandomProbe")); // 获取Thread类里面的threadLocalRandomProbe变量在Thread实例里面的偏移量
    //             SECONDARY = UNSAFE.objectFieldOffset
    //                 (tk.getDeclaredField("threadLocalRandomSecondarySeed")); // 获取Thread类里面的threadLocalRandomSecondarySeed变量在Thread实例里面的偏移量,这个值在LongAdder中会用到
    //         } catch (Exception e) {
    //             throw new Error(e);
    //         }
    //     }


    //      public int nextInt(int bound) {
    //         if (bound <= 0) // 参数校验
    //             throw new IllegalArgumentException(BadBound);
    //         int r = mix32(nextSeed()); // 根据当前线程中的种子产生新种子
    //         int m = bound - 1; // 根据新种子和bound计算新随机数
    //         if ((bound & m) == 0) // power of two
    //             r &= m;
    //         else { // reject over-represented candidates
    //             for (int u = r >>> 1;
    //                  u + m - (r = u % bound) < 0;
    //                  u = mix32(nextSeed()) >>> 1)
    //                 ;
    //         }
    //         return r;
    //     }

    //      final long nextSeed() {
    //         Thread t; long r; // read and update per-thread seed
    //         // UNSAFE.getLong(t, SEED)->获取当前线程中threadLocalRandomSeed变量的值，然后在种子基础上累加GAMMA值作为新种子，而后使用putLong方法把新种子放入当前线程的threadLocalRandomSeed变量中
    //         UNSAFE.putLong(t = Thread.currentThread(), SEED,
    //                        r = UNSAFE.getLong(t, SEED) + GAMMA);
    //         return r;
    //     }
}
